﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CC98.Security;

namespace CC98.Network.Primitives
{
    public class DefaultCC98HttpClientFactory : ICC98HttpClientFactory
    {
        private static readonly object _syncRoot = new object();

        private static volatile ICC98HttpClientFactory _instance;

        public static ICC98HttpClientFactory Instance
        {
            get
            {
                if (_instance == null)
                    lock (_syncRoot)
                        if (_instance == null)
                            _instance = new DefaultCC98HttpClientFactory();
                return _instance;
            }
        }

        private DefaultCC98HttpClientFactory() { }

        /// <summary>
        /// Get a CC98HttpClient for a specify user
        /// This method is thread-safe
        /// </summary>
        /// <param name="username">The username</param>
        /// <returns></returns>
        public CC98HttpClient GetClient(string username)
        {
            if (string.IsNullOrWhiteSpace(username))
                throw new ArgumentException("Invalid username");
            lock (this)
            {
                if (this._clientDict.ContainsKey(username))
                {
                    return this._clientDict[username];
                }
                else
                {
                    var client = new CC98HttpClient(new CC98HttpClientHandler(username));
                    this._clientDict[username] = client;
                    return client;
                }
            }
        }

        /// <summary>
        /// Get client for a specify session
        /// </summary>
        /// <param name="session">The session</param>
        /// <param name="isOverwrite">If true, the new client will overwrite the exists client</param>
        /// <returns></returns>
        public CC98HttpClient GetClient(Session session, bool isOverwrite)
        {
            if (session == null)
                throw new ArgumentNullException("session");
            lock (this)
            {
                if (this._clientDict.ContainsKey(session.Username) && !isOverwrite)
                    throw new InvalidOperationException("User " + session.Username + " has already exists and cannot be overwritten");
                var client = new CC98HttpClient(new CC98HttpClientHandler(session));
                this._clientDict[session.Username] = client;
                return client;
            }
        }

        public async Task<CC98HttpClient> LoginClientAsync(CC98Certificate certificate)
        {
            if (certificate == null)
                throw new ArgumentNullException("certificate");
            throw new NotImplementedException();
        }

        public IEnumerable<CC98HttpClient> GetAllClients()
        {
            throw new NotImplementedException();
        }

        #region private

        private readonly Dictionary<string, CC98HttpClient> _clientDict = new Dictionary<string, CC98HttpClient>();

        #endregion
    }
}
